#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <unistd.h>

#include <stdexcept>
#include <string>

#include "autocall-util.h"
#include "string-util.h"

using std::string;
using std::runtime_error;

std::string&
format(std::string &str,const char *format_arg,...)
{
    va_list apFirstUse;
    va_list apSecondUse;
    va_start(apFirstUse,format_arg);
    va_copy(apSecondUse,apFirstUse);
    AUTOCALL_FUNC(apdestroy) {
        va_end(apSecondUse);
        va_end(apFirstUse);
    };
    AUTOCALL(apdestroy);

    int size = vsnprintf(0,0,format_arg,apFirstUse);
    if (size < 0)
        throw std::runtime_error("");
    std::string::size_type oldSize = str.size();
    str.resize(oldSize + size);
    size = vsnprintf((char*)str.data() + oldSize,size + 1,format_arg,apSecondUse);
    if (size < 0)
        throw std::runtime_error("");

    return str;
}

std::string format(const char *format_arg,...)
{
    va_list apFirstUse;
    va_list apSecondUse;
    va_start(apFirstUse,format_arg);
    va_copy(apSecondUse,apFirstUse);
    AUTOCALL_FUNC(apdestroy) {
        va_end(apSecondUse);
        va_end(apFirstUse);
    };
    AUTOCALL(apdestroy);
    std::string str;

    int size = vsnprintf(0,0,format_arg,apFirstUse);
    if (size < 0)
        throw std::runtime_error("");
    std::string::size_type oldSize = str.size();
    str.resize(oldSize + size);
    size = vsnprintf((char*)str.data() + oldSize,size + 1,format_arg,apSecondUse);
    if (size < 0)
        throw std::runtime_error("");

    return str;
}


bool allspace(const std::string &buf)
{
    for (const char ch : buf) {
        if (!isspace(ch))
            return false;
    }
    return true;
}

void trim(std::string &buf)
{
    const char *ptr = buf.c_str();
    const char *ptr_end = ptr + buf.size();
    for (; *ptr != 0 && isspace(*ptr); ++ptr)
        ;
    if (*ptr == 0) {
        buf.clear();
        return ;
    }
    --ptr_end;
    for (; isspace(*ptr_end); --ptr_end)
        ;
    ++ptr_end;
    size_t ptr_offset = ptr - buf.c_str();
    size_t ptr_end_offset = ptr_end - buf.c_str();

    buf.erase(ptr_end_offset);
    buf.erase(0,ptr_offset);\
    return ;
}

